/*******************************************************************
 * Copyright (C) yel_hb-USTC, 2012                                
 *                                                                  
 * FILE NAME             :  SangerRule.cpp                                 
 * PRINCIPAL AUTHOR      :  yel_hb                               
 * MODULE NAME           :  SangerRule                             
 * LANGUAGE              :  C++                                      
 * TARGET ENVIRONMENT    :  windows                                   
 * DATE OF FIRST RELEASE :  2013/1/11                            
 * DESCRIPTION           :  implement the functions defined it the 
 *							file SangerRule.h
 ******************************************************************/

/*
 * Revision log:
 *
 * Created by yel_hb,2013/1/11
 *
 */

#include <vector>
#include <iostream>
#include "dmvector.h"
#include "SangerRule.h"
#include "kahansum.h"
#include "utils.h"
using namespace std;

SangerRule::SangerRule ( )
{
	eta = 0.01;
	K = 0;
	N = 0;
}

/*
 * N->the dimension of dataset
 * K->the number of linear component to find
 */
SangerRule::SangerRule ( int K, int N, double eta )
{
	this->K = K;
	this->N = N;
	this->eta = eta;
	W.resize ( K );
}

void SangerRule::init ()
{
	int i, j;
	for ( i = 0; i < K; ++i )
	{
		for ( j = 0; j < N; ++j )
		{
			W[i].set ( j, gaussianNormal() );
		}
	}
}

void SangerRule::update ( DMVector X )
{
	int i, j, r;
	KahanSum sum;
	vector<double> Y(K);
	DMVector tmpX, tmpY;
	vector<DMVector> WT(N), WTT;

	for ( i = 0; i < K; ++i )
	{
		Y[i] = W[i].dot ( X );
	}

	for ( i = 0; i < N; ++i )
	{
		for ( j = 0; j < K; ++j )
		{
			WT[i].set( j, W[j].get( i ));
		}
	}
	WTT = WT;

	for ( i = 0; i < N; ++i )
	{
		for ( j = 0; j < K; ++j )
		{
			sum.reset();
			for ( r = 0; r <= j; ++r )
			{
				sum.add ( Y[r] * WTT[i].get ( r ));
			}
			WT[i].set ( j, WT[i].get ( j ) + eta * Y[j] * ( X.get ( i ) - sum.get_sum()));
		}
	}

	for ( i = 0; i < K; ++i )
	{
		for ( j = 0; j < N; ++j )
		{
			W[i].set( j, WT[j].get( i ));
		}
	}
}

vector<DMVector> SangerRule::getW ()
{
	return W;
}